/*
 ------------------------------------------------------------------------------
 Copyright (C) 1996-2001 Id Software, Inc.

 This file is part of the Quake source code.

 The Quake source code is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or (at your
 option) any later version.

 The Quake source code is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 more details.

 You should have received a copy of the GNU General Public License along with
 the Quake source code; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 ------------------------------------------------------------------------------
*/


//
// netChan.h - network channel
//


#ifndef __NETCHAN_H__
#define __NETCHAN_H__


/*
 ==============================================================================

 Network Channels:

 A network channel handles packet compression and decompression, packet
 fragmentation and reassembly, and out of order / duplicate suppression.

 Packet header:
 --------------
 4		Outgoing sequence (bit 31 will be set if this is a fragmented message)
 2		Uncompressed message size
 2		Channel port (only for client to server)
 2		Fragment offset (only if this is a fragmented message)
 2		Fragment size (if < FRAGMENT_SIZE, this is the last fragment)

 If the sequence number is OOB_SEQUENCE, the packet should be handled as an
 out-of-band message instead of as part of a network connection.

 All fragments will have the same sequence numbers.

 The channel port field is a workaround for bad address translating routers
 that sometimes remap the client's source port on a packet during gameplay.
 If the base part of the network address matches and the channel port matches,
 then the channel matches even if the IP port differs. The IP port should be
 updated to the new value before sending out any replies.

 ==============================================================================
*/

#define CLIENT_PACKET_HEADER		8			// Size of a client packet header
#define SERVER_PACKET_HEADER		6			// Size of a server packet header

#define FRAGMENT_SIZE				(MAX_PACKET_SIZE - 12)
#define FRAGMENT_BIT				(1 << 31)

struct netChan_t {
	netSrc_t		sock;
	netAdr_t		remoteAddress;
	int				channelPort;				// Channel port value to write when transmitting

	// Sequencing variables
	int				incomingSequence;
	int				outgoingSequence;

	// Rate variables
	int				incomingRateTime;
	int				incomingRateBytes;
	int				outgoingRateTime;
	int				outgoingRateBytes;

	// Incoming fragment buffer
	int				incomingFragmentSequence;
	int				incomingFragmentSize;
	byte			incomingFragmentBuffer[MAX_MSG_SIZE];

	// Outgoing fragment buffer
	bool			outgoingFragments;
	int				outgoingFragmentBytes;
	int				outgoingFragmentOffset;
	int				outgoingFragmentSize;
	byte			outgoingFragmentBuffer[MAX_MSG_SIZE];
};

// Initializes the network channel subsystem
void			NetChan_Init ();

// Opens a channel to a remote system
void			NetChan_Setup (netChan_t *netChan, netSrc_t sock, const netAdr_t adr, int channelPort);

// Sends a message to a connection, fragmenting if necessary.
// A zero size message will still generate a packet.
void			NetChan_Transmit (netChan_t *netChan, int time, msg_t *msg);

// Sends one fragment of the current message
void			NetChan_TransmitNextFragment (netChan_t *netChan, int time);

// Sends all the remaining fragments of the current message
void			NetChan_TransmitAllFragments (netChan_t *netChan, int time);

// Receives a message from a connection.
// Returns false if the message should not be processed due to being out of
// order or a fragment.
// The msg parameter must be large enough to hold MAX_MSG_SIZE bytes of data,
// because if this is the final fragment of a multi-part message, the entire
// thing will be copied out.
bool			NetChan_Process (netChan_t *netChan, int time, msg_t *msg);


#endif	// __NETCHAN_H__